// Project name:JavaRedis
// Creator:muhong
// Date time:2022/11/13,11:32 下午
// Name:JRedisNoBlockClient

package org.gmh.client;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;

public class JRedisNoBlockClient {
    final Logger logger = LoggerFactory.getLogger(this.getClass());
    private static int DEFAULT_PORT = 9090;

    SocketChannel sc = null;
    SCRead readThread = null;
    private void connect(){
        String host = "127.0.0.1";

        try {
            Selector selector = Selector.open();
            sc = SocketChannel.open();

            SocketAddress address = new InetSocketAddress(host, DEFAULT_PORT);
            boolean isConnect = sc.connect(address);
            sc.configureBlocking(false);
            sc.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE);
            logger.info("连接到服务器："+isConnect);

            // 异步读数据
            readThread = new SCRead(selector);
            readThread.start();
            // 写数据
            ByteBuffer byteBuffer = ByteBuffer.allocate(100);
            Scanner scanner = new Scanner(System.in);
            System.out.print("input:");
            String input = scanner.nextLine();
            while (!"exit".equals(input)) {
                if (!sc.isConnected()){
                    System.out.println("尚未连接到服务器!");
                    continue;
                }
                byteBuffer.put(input.getBytes());
                byteBuffer.flip();
                sc.write(byteBuffer);
                byteBuffer.compact();
                System.out.print("input:");
                input = scanner.nextLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            shutdown();
        }
        shutdown();
    }

    private void shutdown(){
        readThread.setShutdown(true);
        try {
            if (sc != null){
                sc.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static class SCRead extends Thread {

        final Logger logger = LoggerFactory.getLogger(this.getClass());

        private Selector selector;

        private boolean shutdown;

        SCRead(Selector selector){
            this.selector = selector;
        }

        @Override
        public void run() {
            ByteBuffer byteBuffer = ByteBuffer.allocate(100);
            while (!shutdown){
                try {
                    selector.select();
                    Set<SelectionKey> keySet = selector.selectedKeys();
                    if (keySet.isEmpty()){
                        continue;
                    }
                    Iterator<SelectionKey> iterator = keySet.iterator();
                    while (iterator.hasNext()){
                        byteBuffer.clear();
                        SelectionKey key = iterator.next();
                        iterator.remove();
                        if (key.isReadable()) {
                            logger.info("接收到客户端的数据...");
                            SocketChannel client = (SocketChannel) key.channel();
                            int size = client.read(byteBuffer);
                            if (size == -1) {
                                throw new IOException("读完成");
                            }
                            String remoteStr =new String(byteBuffer.array());
                            logger.info(byteBuffer.toString());
                            logger.info(remoteStr);
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }

        public void setShutdown(boolean shutdown) {
            this.shutdown = shutdown;
        }
    }

    public static void main(String[] args) {
        new JRedisNoBlockClient().connect();
    }
}
